#include "SBaseDialog.h"
#include "SImageButton.h"
#include "WidgetResizer.h"
#include <QVBoxLayout>
#include <QStylePainter>
#include <QEvent>
#include <QMouseEvent>
#include <QLabel>

#pragma region TitleBar

DlgTitleBar::DlgTitleBar(SBaseDialog* parent)
	: QWidget(parent), m_dlg(parent)
{
	setMouseTracking(true);
	setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
	setFixedHeight(29);

	QHBoxLayout* titleLayout = new QHBoxLayout();
	titleLayout->setSpacing(0);
	titleLayout->setContentsMargins(0, 0, 0, 0);

	m_titleLabel = new QLabel(this);
	m_titleLabel->setAlignment(Qt::AlignCenter);
	titleLayout->addWidget(m_titleLabel);

	titleLayout->addStretch();

	m_btnReload = new SImageButton(this, "widgets_action_refresh");
	m_btnPin = new SImageButton(this, "widgets_win_pin");
	m_btnPinSel = new SImageButton(this, "widgets_win_pin_selected");
	m_btnFull = new SImageButton(this, "widgets_win_full");
	m_btnRestore = new SImageButton(this, "widgets_win_restore");
	m_btnClose = new SImageButton(this, "widgets_win_close");

	titleLayout->addWidget(m_btnReload);
	titleLayout->addWidget(m_btnPin);
	titleLayout->addWidget(m_btnPinSel);
	titleLayout->addWidget(m_btnFull);
	titleLayout->addWidget(m_btnRestore);
	titleLayout->addWidget(m_btnClose);

	dlgTypeChanged();

	setLayout(titleLayout);

	connect(m_btnClose, &SImageButton::clicked, m_dlg, &SBaseDialog::reject);
	connect(m_btnReload, &SImageButton::clicked, this, &DlgTitleBar::onBtnClicked);
	connect(m_btnPin, &SImageButton::clicked, this, &DlgTitleBar::onBtnClicked);
	connect(m_btnPinSel, &SImageButton::clicked, this, &DlgTitleBar::onBtnClicked);
	connect(m_btnFull, &SImageButton::clicked, this, &DlgTitleBar::onBtnClicked);
	connect(m_btnRestore, &SImageButton::clicked, this, &DlgTitleBar::onBtnClicked);
	connect(this, &QWidget::windowTitleChanged, this, &DlgTitleBar::setTitle);
}

void DlgTitleBar::dlgTypeChanged()
{
	bool isDlg = m_dlg->m_winType == SBaseDialog::WindowType::kDialog;
	bool isFixedDlg = m_dlg->m_winType == SBaseDialog::WindowType::kFixedDialog;
	bool isChildWindow = m_dlg->m_winType == SBaseDialog::WindowType::kChild;

	m_btnReload->setVisible(m_webDlg);
	m_btnPin->setVisible(isDlg && !m_dlg->windowFlags().testFlag(Qt::WindowStaysOnTopHint));
	m_btnPinSel->setVisible(isDlg && m_dlg->windowFlags().testFlag(Qt::WindowStaysOnTopHint));
	m_btnFull->setVisible(isDlg && !m_dlg->isMaximized());
	m_btnRestore->setVisible(isDlg && m_dlg->isMaximized());
	m_btnClose->setVisible(isDlg || isFixedDlg);
}

void DlgTitleBar::setTitle(const QString& title)
{
	m_titleLabel->setText(title);
}

void DlgTitleBar::setWebDlg(bool v)
{
	m_webDlg = v;
	m_btnReload->setVisible(m_webDlg);
}

void DlgTitleBar::onBtnClicked()
{
	if (sender() == m_btnPin)
	{
		m_btnPin->setVisible(false);
		m_btnPinSel->setVisible(true);
		m_dlg->setWindowFlag(Qt::WindowStaysOnTopHint);
		m_dlg->show();
	}
	else if (sender() == m_btnPinSel)
	{
		m_btnPin->setVisible(true);
		m_btnPinSel->setVisible(false);
		m_dlg->setWindowFlag(Qt::WindowStaysOnTopHint, false);
		m_dlg->show();
	}
	else if (sender() == m_btnFull)
	{
		m_btnFull->setVisible(false);
		m_btnRestore->setVisible(true);
		m_dlg->showMaximized();
	}
	else  if (sender() == m_btnRestore)
	{
		m_btnFull->setVisible(true);
		m_btnRestore->setVisible(false);
		m_dlg->showNormal();
	}
}

void DlgTitleBar::mousePressEvent(QMouseEvent* e)
{
	m_dragPos = e->globalPos();
}

void DlgTitleBar::mouseMoveEvent(QMouseEvent *e)
{
	QPoint offset = e->globalPos() - m_dragPos;
	if (e->buttons().testFlag(Qt::LeftButton) && offset.manhattanLength() >= 5)
	{
		m_dlg->move(m_dlg->pos() + offset);
		m_dragPos = e->globalPos();
		m_dlg->moving(m_dlg);
	}
	
	return QWidget::mouseMoveEvent(e);
}

void DlgTitleBar::mouseDoubleClickEvent(QMouseEvent* event)
{
	m_btnFull->setVisible(m_dlg->isMaximized());
	m_btnRestore->setVisible(!m_dlg->isMaximized());

	if (m_dlg->isMaximized())
		m_dlg->showNormal();
	else
		m_dlg->showMaximized();
}

#pragma endregion

SBaseDialog::SBaseDialog(WindowType type, QWidget* parent)
	:QFrame(parent)
{
	setWindowFlag(Qt::FramelessWindowHint);
	setStyleSheet("SBaseDialog {border: 1px solid #0C4F44;\nborder-radius:2px}");

	QVBoxLayout* layout = new QVBoxLayout(this);
	layout->setContentsMargins(2, 0, 2, 2);
	m_titleBar = new DlgTitleBar(this);
	layout->addWidget(m_titleBar);
	setLayout(layout);

	m_resizer = new WidgetResizer(this);
	setWindowType(type);
}

SBaseDialog::~SBaseDialog()
{

}

void SBaseDialog::paintEvent(QPaintEvent* event)
{
	if (m_winType != WindowType::kChild)
	{
		QColor c(isActiveWindow() ? 0x0C4F44 : 0x193D37);
		QStylePainter painter(this);
		QRect r(rect().topLeft(), QSize(rect().width(), 30));
		painter.fillRect(r, c);
	}
	
}

void SBaseDialog::showEvent(QShowEvent* event)
{
	static bool s_initialized = false;
	if (!s_initialized)
	{
		if (sizePolicy() == QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed))
		{
		}

		s_initialized = true;
	}
	QFrame::showEvent(event);
}

void SBaseDialog::doModal()
{
	setWindowModality(Qt::WindowModality::ApplicationModal);
	show();
}

void SBaseDialog::setWindowType(WindowType type)
{
	if (m_winType != type)
	{
		m_winType = type;
		if (type == WindowType::kDialog || type == WindowType::kFixedDialog)
		{
			if (m_titleBar)
				m_titleBar->show();
		}
			
		else
		{
			if (m_titleBar)
				m_titleBar->hide();
		}

		if(m_titleBar)
			m_titleBar->dlgTypeChanged();

		m_resizer->enable(m_winType == WindowType::kDialog);
		show();

	}
	
}

void SBaseDialog::setTitle(const QString& title)
{
	m_titleBar->setTitle(title);
}

void SBaseDialog::setContentWidget(QWidget* w, bool web)
{
	m_webContent = web;
	if(m_contentWidget != nullptr)
		layout()->removeWidget(m_contentWidget);

	resize(w->width() + 5, w->height() + 33);
	layout()->addWidget(w);
	w->setMouseTracking(true);
	m_contentWidget = w;
}

void SBaseDialog::removeContentWidget() 
{
	layout()->removeWidget(m_contentWidget);
	m_contentWidget = nullptr;
}

void SBaseDialog::detach()
{
	setParent(nullptr);
	setWindowType(WindowType::kDialog);
}

void SBaseDialog::done(QDialog::DialogCode code)
{
	finished(code);
	if (code == QDialog::Accepted)
		accepted();
	else
		rejected();

	close();
}